package be.kuleuven.mume.hulpklassen;

import java.util.ArrayList;
import java.util.List;

import be.kuleuven.mume.R;

import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.widget.AbsListView;
import android.widget.Toast;
import android.widget.AbsListView.OnScrollListener;
import android.widget.ListView;

public abstract class DataFetcher<DataType> implements Runnable{
	private static final String TAG = "DataFetcher";
	private static final int BUFFERED_ITEMS = 5;
	
	private Handler handler;
	private String url;
	private JSONParser<DataType> parser;
	private int page = 0;
	private int rpp = 10;
	private Boolean hasMoreData = true;
	private Thread t;
	private List<DataType> dataList = new ArrayList<DataType>();
	private Context context;
	
	public abstract void DataReceived();
	
	public DataFetcher(JSONParser<DataType> parser, String url, ListView table, final List<DataType> dataList, Context context){
		
		assert (parser != null);
		assert (url != null && url != "");
		assert (dataList != null);
		assert (context != null);
		
		this.url = url;
		this.parser = parser;
		this.dataList = dataList;
		this.context = context;
		this.handler = new Handler() {
	        @SuppressWarnings("unchecked")
			@Override
	           public void handleMessage(Message message) {
	        	   dataList.addAll((List<DataType>)message.obj);
	        	   DataReceived();
	           }
	       };
	       
	       if(table!=null){
	    	   table.setOnScrollListener(new OnScrollListener() {
	    		   public void onScrollStateChanged(AbsListView view, int scrollState) {
	    		   }
	    		   public void onScroll(AbsListView view, int firstVisibleItem,
	    				   int visibleItemCount, int totalItemCount) {
	    			   if((visibleItemCount+firstVisibleItem+BUFFERED_ITEMS) > totalItemCount)
	    				   fetchDataInNewThread();
	    		   }
	    	   });
	       }
	}
	
	public void setRpp(int rpp){
		if(rpp < 0)
			Log.e(TAG, "Illegal value: rpp must be at least 1");
		this.rpp = rpp;
	}
	
	public int getRpp(){
		return rpp;
	}
	
	public boolean hasMoreData(){
		return this.hasMoreData;
	}
	
	public List<DataType> getData() {
		return this.dataList;
	}
	
	public void fetchDataInNewThread() {
    	if(!hasMoreData)
    		return;
    	
    	if((t == null) || !t.isAlive()) {
			t = new Thread(this);
			t.start();
    	}
	}
	
    public void run() {
		String jString;
		try {
			String argumentSepp = "?";
			if(url.contains("?"))
				argumentSepp = "&";
			
			jString = HttpHelper.doGet(url + argumentSepp + "page=" + page + "&rpp=" + rpp, context);
			List<DataType> data = parser.parse(jString);
			//rpp is not implemented with some pages.
			if(data.size() < rpp || data.size() > rpp) {
				hasMoreData = false;
				Log.i(TAG, "All Data fetched");
			}
			page++;
			Message message = handler.obtainMessage(1, data);
			handler.sendMessage(message);
		} catch (Exception e) {
			Toast.makeText(context, R.string.serverError, 10).show();
			Log.e(TAG, "Exception", e);
		}
   }
    
    public void refresh(){
    	hasMoreData = true;
    	dataList.clear();
    	fetchDataInNewThread();
    }
}
